package demo;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

public class JvmMemoryTest {
    private static final AtomicBoolean running = new AtomicBoolean(true);
    private static final List<List<Integer>> dataList = new ArrayList<>();
    
    public static void main(String[] args) {
        // 启动打印线程
        Thread printThread = new Thread(new PrintTask(), "Print-Thread");
        printThread.start();
        
        // 启动添加数据的线程
        Thread addThread = new Thread(new AddDataTask(), "AddData-Thread");
        addThread.start();
        
        // 等待添加线程结束
        try {
            addThread.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 停止打印线程
        running.set(false);
        System.out.println("测试结束，数据列表大小: " + dataList.size());
    }
    
    /**
     * 打印任务 - 每5秒打印一次内存信息
     */
    static class PrintTask implements Runnable {
        @Override
        public void run() {
            System.out.println("打印线程启动，开始监控内存情况...");
            
            while (running.get()) {
                try {
                    // 每5秒打印一次内存信息
                    Thread.sleep(2000);
                    
                    // 获取并打印内存指标
                    JvmMemoryMetrics metrics = JvmMemoryMonitor.getMemoryMetrics();
                    printMetricsInChinese(metrics);
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            System.out.println("打印线程结束");
        }
        
        /**
         * 使用中文打印内存指标
         */
        private void printMetricsInChinese(JvmMemoryMetrics metrics) {
            System.out.println("\n===== JVM 内存监控报告 =====");
            System.out.println("当前时间: " + new java.util.Date());
            System.out.println("数据列表大小: " + dataList.size() + " 个列表");
            
            // 堆内存信息
            System.out.println("\n【堆内存使用情况】");
            System.out.printf("已使用: %.2f MB%n", metrics.getHeapUsed() / 1024.0 / 1024.0);
            System.out.printf("已提交: %.2f MB%n", metrics.getHeapCommitted() / 1024.0 / 1024.0);
            System.out.printf("最大值: %.2f MB%n", metrics.getHeapMax() / 1024.0 / 1024.0);
            System.out.printf("使用率: %.1f%%%n", 
                (metrics.getHeapUsed() * 100.0 / metrics.getHeapCommitted()));
            
            // 非堆内存信息
            System.out.println("\n【非堆内存使用情况】");
            System.out.printf("元空间已使用: %.2f MB%n", metrics.getMetaspaceUsed() / 1024.0 / 1024.0);
            System.out.printf("元空间已提交: %.2f MB%n", metrics.getMetaspaceCommitted() / 1024.0 / 1024.0);
            System.out.printf("元空间最大值: %.2f MB%n", metrics.getMetaspaceMax() / 1024.0 / 1024.0);
            
            // 直接内存信息
            System.out.println("\n【直接内存使用情况】");
            System.out.printf("已使用: %.2f MB%n", metrics.getDirectMemoryUsed() / 1024.0 / 1024.0);
            
            // 内存池信息
            System.out.println("\n【内存池详情】");
            for (JvmMemoryMetrics.MemoryPoolMetrics pool : metrics.getMemoryPools()) {
                if (pool.getMax() > 0) { // 只显示有最大值的池
                    System.out.printf("%s (%s): %.1f%% 使用率%n",
                            getChinesePoolName(pool.getName()),
                            pool.getMemoryType(),
                            (pool.getUsed() * 100.0 / pool.getCommitted()));
                }
            }
            
            // GC 信息
            System.out.println("\n【垃圾回收统计】");
            for (JvmMemoryMetrics.GcMetrics gc : metrics.getGcMetrics()) {
                System.out.printf("%s: %d 次回收, 耗时 %d ms%n",
                        getChineseGcName(gc.getName()),
                        gc.getCount(),
                        gc.getTime());
                if (gc.getLastCause() != null && !"Unknown".equals(gc.getLastCause())) {
                    System.out.printf("  最近原因: %s%n", getChineseGcCause(gc.getLastCause()));
                }
            }
            
            // CPU 信息
            System.out.println("\n【CPU 使用情况】");
            System.out.printf("JVM 进程CPU使用率: %.1f%%%n", metrics.getProcessCpuUsage());
            System.out.printf("系统CPU使用率: %.1f%%%n", metrics.getSystemCpuUsage());
            
            System.out.println("===================================\n");
        }
        
        /**
         * 获取中文内存池名称
         */
        private String getChinesePoolName(String englishName) {
            switch (englishName) {
                case "Eden Space": return "伊甸园区";
                case "Survivor Space": return "幸存者区";
                case "Tenured Gen": return "老年代";
                case "Old Gen": return "老年代";
                case "Metaspace": return "元空间";
                case "Code Cache": return "代码缓存";
                case "Compressed Class Space": return "压缩类空间";
                default: return englishName;
            }
        }
        
        /**
         * 获取中文GC名称
         */
        private String getChineseGcName(String englishName) {
            if (englishName.contains("Young")) return "年轻代GC";
            if (englishName.contains("Old")) return "老年代GC";
            if (englishName.contains("Full")) return "Full GC";
            return englishName;
        }
        
        /**
         * 获取中文GC原因
         */
        private String getChineseGcCause(String englishCause) {
            switch (englishCause) {
                case "Allocation Failure": return "分配失败";
                case "Metadata GC Threshold": return "元数据GC阈值";
                case "System.gc()": return "系统调用GC";
                case "G1 Evacuation Pause": return "G1回收暂停";
                case "G1 Humongous Allocation": return "G1大对象分配";
                default: return englishCause;
            }
        }
    }
    
    /**
     * 添加数据任务 - 持续添加数据直到超过500个列表
     */
    static class AddDataTask implements Runnable {
        @Override
        public void run() {
            System.out.println("数据添加线程启动，目标创建500个数据列表...");
            
            int listCount = 0;
            while (listCount < 500 && running.get()) {
                try {
                    // 创建一个包含1000个整数的列表
                    List<Integer> newList = new ArrayList<>();
                    for (int i = 0; i < 1000; i++) {
                        newList.add(i);
                    }
                    
                    // 添加到全局列表
                    synchronized (dataList) {
                        dataList.add(newList);
                        listCount = dataList.size();
                    }
                    
                    // 稍微休息一下，避免太快
                    Thread.sleep(10);
                    
                    // 每添加100个列表打印一次进度
                    if (listCount % 100 == 0) {
                        System.out.println("已创建 " + listCount + " 个数据列表");
                    }
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            
            System.out.println("数据添加完成，总共创建了 " + listCount + " 个数据列表");
            System.out.println("总数据量: " + (listCount * 1000) + " 个整数");
        }
    }
}